#include"mystdio.h"
#include<string.h>
#include <sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<malloc.h>
#include<assert.h>
MY_FILE* my_fopen(const char* path,const char* mode)
{
  //1.识别标志位
  int flag=0;
  if(strcmp(mode,"r")==0) flag|=O_RDONLY;
  else if(strcmp(mode,"w")==0) flag|=(O_CREAT|O_WRONLY|O_TRUNC);
  else if(strcmp(mode,"a")==0) flag|=(O_CREAT|O_WRONLY|O_APPEND);
  else{
    //other operator.....
    //eg: "r+","w+"......
  }
  //2.尝试打开文件
  mode_t m=0666;
  int fd=0;
  //如果需要创建文件，那么我们特殊判断一下，同时将权限默认设成666
  if(flag & O_CREAT) fd=open(path,flag,m);
  //如果不需要创建新的文件
  else fd=open(path,flag);
 //如果打开失败，那么我们的文件描述符fd就小于0
  if(fd<0) return NULL;

  //3.给用户返回一个MY_FILE对象，需要先进行构造
  MY_FILE* mf=(MY_FILE*)malloc(sizeof(MY_FILE));
  if(mf==NULL)
  {
    close(fd);
    return NULL;
  }
  //4.上面也已经创建了MY_FILE对象，接下来初始化MY_FILE对象
  mf->fd=fd;
  mf->flags=0;
  mf->flags=BUFF_LINE;
  memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
  mf->current=0;
  //mf->outputbuffer[0]=0;  //初始化缓冲区

  //5.返回打开的文件
  return mf;
}
int my_fflush(MY_FILE* fp)
{
  assert(fp);
  //将用户缓冲区中的数据，通过系统调用接口，冲刷给os
  write(fp->fd,fp->outputbuffer,fp->current);
  fp->current=0;
  
  fsync(fp->fd);
  return 0;
}
//我们今天返回的就是一个实际写入的字节数，，原函数是返回个数的
size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* stream)
//ptr是要写入的缓冲区，size是大小，nmemb是个数，stream是流，stream->outputbuff是用户及缓冲区
{
  //1.缓冲区如果满了，就直接写入
  if(stream->current==NUM) my_fflush(stream);

  //2.根据缓冲区的剩余情况，进行数据拷贝即可
  size_t user_size=size*nmemb;
  size_t my_size=NUM-stream->current;

  size_t writen=0;
  if(my_size>=user_size)
  {
    memcpy(stream->outputbuffer+stream->current,ptr,user_size);
    //3.更新计数器字段
    stream->current+=user_size;
    writen=user_size;
  }
  else{
    memcpy(stream->outputbuffer+stream->current,ptr,my_size);
    //3.更新计数器字段
    stream->current+=my_size;
    writen=my_size;
  }
  //4. 开始刷新后，高效体现在下面代码
  if(stream->flags&BUFF_ALL)
  {
    if(stream->current==NUM) my_fflush(stream);
  }
  else if(stream->flags=BUFF_LINE)
  {
    if(stream->outputbuffer[stream->current-1]=='\n') my_fflush(stream);
  }
  else{
    //TODO
  }
  return writen;
}
int my_fclose(MY_FILE* fp)
{
  assert(fp);
  //1.冲刷缓冲区
  if(fp->current>0) my_fflush(fp);
  //2.关闭文件
  close(fp->fd);
  //3.释放堆空间
  free(fp);
  //4.指针置为NULL---可以不设置
  fp=NULL;
  return 0;
}
